package com.mccken.demo.classload;

import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;

import lombok.SneakyThrows;

/**
 * 自定义类加载器，继承了ClassLoader，但是父加载器是null，所以是根加载器
 * 加载了指定目录下的class文件，然后调用defineClass方法，将class的字节码数组转换成Class对象
 * 
 * 只需要重写findClass方法即可，因为ClassLoader中的loadClass方法最终也是调用的findClass方法
 * 
 * 接下来要做的事情是：
 * 1. 解析java文件，生成class文件，然后加载class文件，调用defineClass方法，将class的字节码数组转换成Class对象
 * 2. 监听java文件的变化，一旦java文件发生变化，重新解析java文件，生成class文件，然后加载class文件，调用defineClass方法，将class的字节码数组转换成Class对象
 * 
 * 
 * @program: mccken-collect
 * @description:
 * @author: mccken
 * @create: 2023-11-23 12:55
 **/
public class TestClassLoader extends ClassLoader {
	public TestClassLoader(ClassLoader parent) {
		super(parent);
	}
	
	@Override
	protected Class<?> findClass(String name) throws ClassNotFoundException {
		// 1、获取class文件二进制字节数组
		// 2、调用defineClass方法，将class的字节码数组转换成Class对象
		String dir = "/Users/mccken/Downloads/temp/compiler/";
		byte[] bytes = this.loadFileToByte(dir + name + ".class");
		return defineClass(name, bytes, 0, bytes.length);
	}
	
	@SneakyThrows
	private static byte[] loadFileToByte(String path) {
		FileChannel channel = FileChannel.open(Paths.get(path), StandardOpenOption.READ);
		ByteBuffer buf = ByteBuffer.allocate((int) channel.size());
		channel.read(buf);
		channel.close();
		return buf.array();
	}
	
}
